package com.eidos.blogs.openapi.thread.seckill;

import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

/**
 * @author ： Eidos
 * @date ：Created in 2021/1/27
 * @description：
 * @modified By：
 * @version: 1.0
 */
public class TemplateFutureTask<T> implements Runnable {

    // 程序执行的结果
    private T result;

    // 要执行的任务
    private Callable<T> callable;

    // 任务运行的状态
    private volatile int state = NEW;

    // 任务运行的状态值
    private static final int NEW = 0;
    private static final int RUNNING = 1;
    private static final int FINISHED = 2;

    // 获取结果的线程等待队列
    LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>(100);

    // 执行当前FutureTask的线程，用CAS进行争抢
    AtomicReference<Thread> runner = new AtomicReference<>();

    public TemplateFutureTask(Callable<T> task) {
        this.callable = task;
    }

    @Override
    public void run() {
        // 判断当前对象的状态，如果是New且抢锁成功就执行
        if (state != NEW || !runner.compareAndSet(null, Thread.currentThread())) return;
        state = RUNNING;
        try {
            result = callable.call();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            state = FINISHED;
        }

        // 方法执行完，唤醒所有线程
        while (true) {
            Thread waiterThread = waiters.poll();
            if (waiterThread == null) break;
            LockSupport.unpark(waiterThread);
        }
    }

    public T get() {
        // 如果状态不是FINISHED，则进入等待队列
        if (state != FINISHED) {
            waiters.offer(Thread.currentThread());
        }
        while (state != FINISHED) {
            LockSupport.park();
        }
        return result;
    }
}
